﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using RZ.Web;
using System.Diagnostics;

namespace NativeWebSurf
{
    public sealed partial class HTMLInspector : UserControl
    {
        String htmlBody;

        public String HtmlBody
        {
            get { return htmlBody; }
            set { htmlBody = value; }
        }

        public void Parse()
        {
            ClearStructure();

            var parser = new HtmlParser(this.htmlBody);

            if (!parser.MoveToHeadTag())
            {
                MessageBox.Show(this, "This seems not be HTML content!?", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }

            this.Cursor = Cursors.WaitCursor;

            Boolean hasMatch;
            var tagBlock = parser.GrabCurrentTag(out hasMatch);

            if (!hasMatch)
                MessageBox.Show(this, "This is not well-form HTML... Result may be inaccurate.", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Warning);

            BuildTagTree(tagBlock);

            this.Cursor = Cursors.Default;
        }

        IList<Int32> currentFind = null;

        public HTMLInspector()
        {
            InitializeComponent();
        }

        void BuildTagTree(HtmlContentBlock tagBlock)
        {
            AddTreeNode(this.scrTagTree.Nodes, tagBlock);
        }

        void ClearStructure()
        {
            this.scrTagTree.Nodes.Clear();
            this.txtContent.Clear();
            this.scrProperties.Items.Clear();

            this.currentFind = null;
        }

        TreeNode AddTreeNode(TreeNodeCollection nodes, HtmlContentBlock block)
        {
            var newNode = nodes.Add("<" + block.TagName + ">");

            newNode.Tag = block;

            return newNode;
        }

        TreeNode AddTreeNode(TreeNodeCollection nodes, HtmlContentText text)
        {
            var newNode = nodes.Add(text.ToString());

            newNode.Tag = text;

            return newNode;
        }

        private void TagTreeOnNodeSelection(object sender, TreeViewEventArgs e)
        {
            UpdateTreeNode(e.Node);
            UpdatePropertiesView(e.Node.Tag as HtmlContentHeadTag);
            UpdateContent(e.Node.Tag as HtmlContentText);
        }

        private void UpdateContent(HtmlContentText htmlContentText)
        {
            if (htmlContentText == null)
                this.txtContent.Clear();
            else
                this.txtContent.Text = htmlContentText.ToString();
        }

        private void UpdateTreeNode(TreeNode treeNode)
        {
            var block = treeNode.Tag as HtmlContentBlock;

            if (block == null || block.Count == treeNode.Nodes.Count)
                return;

            SynchronizeTreeNode(treeNode, block);
        }

        private void SynchronizeTreeNode(TreeNode treeNode, HtmlContentBlock block)
        {
            this.scrTagTree.BeginUpdate();

            treeNode.Nodes.Clear();

            foreach (var innerContent in block)
            {
                var innerBlock = innerContent as HtmlContentBlock;

                if (innerBlock != null)
                    AddTreeNode(treeNode.Nodes, innerBlock);
                else
                    AddTreeNode(treeNode.Nodes, (HtmlContentText)innerContent);
            }

            this.scrTagTree.EndUpdate();
        }

        private void UpdatePropertiesView(HtmlContentHeadTag htmlContentHeadTag)
        {
            this.scrProperties.BeginUpdate();
            this.scrProperties.Items.Clear();

            if (htmlContentHeadTag != null)
                foreach (var attributeName in htmlContentHeadTag.Attributes.Keys)
                {
                    var lvi = new ListViewItem(attributeName);

                    lvi.SubItems.Add(htmlContentHeadTag.Attributes[attributeName]);

                    this.scrProperties.Items.Add(lvi);
                }

            this.scrProperties.EndUpdate();
        }

        private void TagInputOnEnter(object sender, EventArgs e)
        {
            this.inpFindTag.SelectAll();
        }

        private void ButtonOnResetFind(object sender, EventArgs e)
        {
            this.currentFind = null;
        }

        private void FindTagButton_Click(object sender, EventArgs e)
        {
            var rootBlock = (HtmlContentBlock) this.scrTagTree.Nodes[0].Tag;

            this.currentFind = rootBlock.FindTag(this.inpFindTag.Text, this.currentFind);

            if (this.currentFind == null)
                MessageBox.Show(this, "Not found", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
            else
            {
                var treeNode = this.scrTagTree.Nodes[0];
                var contentBlock = (HtmlContentBlock)treeNode.Tag;

                for (var nodeIndex = 0; nodeIndex < this.currentFind.Count; ++nodeIndex)
                {
                    if (treeNode.Nodes.Count != contentBlock.Count)
                        SynchronizeTreeNode(treeNode, contentBlock);

                    Debug.Assert(treeNode.Nodes.Count == contentBlock.Count);

                    treeNode = treeNode.Nodes[this.currentFind[nodeIndex]];
                    contentBlock = (HtmlContentBlock) treeNode.Tag;
                }

                this.scrTagTree.SelectedNode = treeNode;
            }
        }

        private void txtResponse_TextChanged(object sender, EventArgs e)
        {

        }
    }
}
